using System;
using SqlSugar;

namespace Repository.sugar
{
    public class DbContext
    {
        private static string _connectionString;
        private static DbType _dbType;
        private SqlSugarClient _db;

        public static string ConnectionString
        {
            get{
                return _connectionString;
            }
            set {_connectionString = value;}
        }

        /// <summary>
        /// 连接库类型
        /// </summary>
        /// <value></value>
        public static DbType DbType
        {
            get{return _dbType;}
            set {_dbType = value;}
        }

        /// <summary>
        /// 数据连接对象
        /// </summary>
        /// <value></value>
        public SqlSugarClient Db
        {
            get{return _db;}
            set {_db = value;}
        }

        public static DbContext Context
        {
            get {return new DbContext();}
        }

        private DbContext()
        {
            if(string.IsNullOrEmpty(_connectionString)) throw new ArgumentNullException("数据库联接字符串为空");
            _db = new SqlSugarClient(new ConnectionConfig(){
                ConnectionString = _connectionString,
                DbType = _dbType,
                IsAutoCloseConnection = true,
                IsShardSameThread = true,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //DataInfoCacheService = new HttpRuntimeCache()
                },
                MoreSettings = new ConnMoreSettings()
                {
                    //IsWithNoLockQuery = true,
                    IsAutoRemoveDataCache = true
                }
            });
            
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自动关闭连接</param>
        private DbContext(bool blnIsAutoCloseConnection)
        {
            if (string.IsNullOrEmpty(_connectionString)) throw new ArgumentNullException("数据库连接字符串为空");
            
            _db = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = _connectionString,
                DbType = _dbType,
                IsAutoCloseConnection = blnIsAutoCloseConnection,
                IsShardSameThread = true,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //DataInfoCacheService = new HttpRuntimeCache()
                },
                MoreSettings = new ConnMoreSettings()
                {
                    //IsWithNoLockQuery = true,
                    IsAutoRemoveDataCache = true
                }
            });
        }

        #region 实例方法
        /// <summary>
        /// 获取数据库对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public SimpleClient<T> GetEntityDB<T>() where T : class,new()
        {
            return new SimpleClient<T>(_db);
        }

        public SimpleClient<T> GetEntityDB<T>(SqlSugarClient db) where T: class,new()
        {
            return new SimpleClient<T>(db);
        }

        #region 静态方法
        /// <summary>
        /// 获取一个 DbContext
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自动关闭连接（false，需要手动关闭db）</param>
        /// <returns></returns>
        public static DbContext GetDbContext(bool blnIsAutoCloseConnection = true)
        {
            return new DbContext(blnIsAutoCloseConnection);
        }

        public static void Init(string strConnString,DbType enmDbType = SqlSugar.DbType.SqlServer)
        {
            _connectionString = strConnString;
            _dbType = enmDbType;
        }
        
        /// <summary>
        /// 创建一个连接配置
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自动关闭连接</param>
        /// <param name="blnIsShardSameThread">是否夸类事务</param>
        /// <returns></returns>
        public static ConnectionConfig GetConnectionConfig(bool blnIsAutoCloseConnection = true,bool blnIsShardSameThread = false)
        {
            ConnectionConfig config = new ConnectionConfig()
            {
                ConnectionString = _connectionString,
                DbType = _dbType,
                IsAutoCloseConnection = blnIsAutoCloseConnection,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    //DataInfoCacheService = new HttpRuntimeCache()
                },
                IsShardSameThread = blnIsShardSameThread
            };
            return config;
        }
        #endregion

        #region 根据数据库表生产实体类
        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// 作　　者:Blog.Core
        /// </summary>       
        /// <param name="strPath">实体类存放路径</param>
        public void CreateClassFileByDBTalbe(string strPath)
        {
            CreateClassFileByDBTalbe(strPath, "Km.PosZC");
        }
        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// 作　　者:Blog.Core
        /// </summary>
        /// <param name="strPath">实体类存放路径</param>
        /// <param name="strNameSpace">命名空间</param>
        public void CreateClassFileByDBTalbe(string strPath, string strNameSpace)
        {
            CreateClassFileByDBTalbe(strPath, strNameSpace, null);
        }
        /// <summary>
        /// 功能描述:根据数据库表生产实体类
        /// 作　　者:Blog.Core
        /// </summary>
        /// <param name="strPath"></param>
        /// <param name="strNameSpace"></param>
        /// <param name="lstTableNames"></param>
        public void CreateClassFileByDBTalbe(
            string strPath,
            string strNameSpace,
            string[] lstTableNames) 
        {
            CreateClassFileByDBTalbe(strPath, strNameSpace, lstTableNames, string.Empty);
        }
        /// <summary>
        /// 根据数据库表生产实体类
        /// </summary>
        /// <param name="strPath">实体类存放的路径</param>
        /// <param name="strNameSpace">命名空间</param>
        /// <param name="lstTableNames">生成制定的表</param>
        /// <param name="strInterface">实现的接口</param>
        /// <param name="blnSerializable"></param>
        public void CreateClassFileByDBTalbe(
          string strPath,
          string strNameSpace,
          string[] lstTableNames,
          string strInterface,
          bool blnSerializable = false)
        {
            if (lstTableNames != null && lstTableNames.Length > 0)
            {
                _db.DbFirst.Where(lstTableNames).IsCreateDefaultValue().IsCreateAttribute()
                    .SettingClassTemplate(p => p = @"
                    {using}
                    namespace {Namespace}
                    {
                        {ClassDescription}{SugarTable}" + (blnSerializable ? "[Serializable]" : "") + @"
                        public partial class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @"
                        {
                            public {ClassName}()
                            {
                                {Constructor}
                            }
                            {PropertyName}
                        }
                    }
                    ")
                    .SettingPropertyTemplate(p => p = @"
                        {SugarColumn}
                        public {PropertyType} {PropertyName}
                        {
                            get
                            {
                                return _{PropertyName};
                            }
                            set
                            {
                                if(_{PropertyName}!=value)
                                {
                                    base.SetValueCall(" + "\"{PropertyName}\",_{PropertyName}" + @");
                                }
                                _{PropertyName}=value;
                            }
                        }")
                    .SettingPropertyDescriptionTemplate(p => p = "          private {PropertyType} _{PropertyName};\r\n" + p)
                    .SettingConstructorTemplate(p => p = "              this._{PropertyName} ={DefaultValue};")
                    .CreateClassFile(strPath, strNameSpace);
            }
            else
            {
                _db.DbFirst.IsCreateAttribute().IsCreateDefaultValue()
                    .SettingClassTemplate(p => p = @"
                        {using}
                        namespace {Namespace}
                        {
                            {ClassDescription}{SugarTable}" + (blnSerializable ? "[Serializable]" : "") + @"
                            public partial class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @"
                            {
                                public {ClassName}()
                                {
                                    {Constructor}
                                }
                                {PropertyName}
                            }
                        }
                        ")
                    .SettingPropertyTemplate(p => p = @"
                        {SugarColumn}
                        public {PropertyType} {PropertyName}
                        {
                            get
                            {
                                return _{PropertyName};
                            }
                            set
                            {
                                if(_{PropertyName}!=value)
                                {
                                    base.SetValueCall(" + "\"{PropertyName}\",_{PropertyName}" + @");
                                }
                                _{PropertyName}=value;
                            }
                        }")
                    .SettingPropertyDescriptionTemplate(p => p = "          private {PropertyType} _{PropertyName};\r\n" + p)
                    .SettingConstructorTemplate(p => p = "              this._{PropertyName} ={DefaultValue};")
                    .CreateClassFile(strPath, strNameSpace);
            }
        }
        #endregion
        #endregion


    }
}
